Consider adding transparent i18 with simple on-the-fly locale switching to your appliction via I18NInterceptor. The main idea: package neuro.util.xwork; import com.opensymphony.xwork.ActionSupport; import com.opensymphony.xwork.ActionInvocation; import com.opensymphony.xwork.interceptor.Interceptor; import java.util.Locale; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * I18nInterceptor * @author Aleksei Gopachenko */ public class I18nInterceptor implements Interceptor { protected static final Log log = LogFactory.getLog(I18nInterceptor.class); public static final String DEFAULT_SESSION_ATTRIBUTE = "WW_TRANS_I18N_LOCALE"; public static final String DEFAULT_PARAMETER = "request_locale"; protected String parameterName = DEFAULT_PARAMETER; protected String attributeName = DEFAULT_SESSION_ATTRIBUTE; /** */ public I18nInterceptor() { if(log.isDebugEnabled()) log.debug("new I18nInterceptor()"); } public void setParameterName(String parameterName) { this.parameterName = parameterName; } public void setAttributeName(String attributeName) { this.attributeName = attributeName; } /** */ public void init() { if(log.isDebugEnabled()) log.debug("init()"); } /** */ public void destroy() { if(log.isDebugEnabled()) log.debug("destroy()"); } /** */ public String intercept(ActionInvocation invocation) throws Exception { if(log.isDebugEnabled()) log.debug("intercept '" +invocation.getProxy().getNamespace()+"/" +invocation.getProxy().getActionName()+"' { "); //get requested locale Object requested_locale = invocation.getInvocationContext().getParameters().get(parameterName); if(requested_locale!=null && requested_locale.getClass().isArray() && ((Object[])requested_locale).length==1) { requested_locale=((Object[])requested_locale)[0]; } if(log.isDebugEnabled()) log.debug("requested_locale="+requested_locale); //save it in session if (requested_locale!=null) { Locale locale = (requested_locale instanceof Locale)? (Locale) requested_locale : localeFromString(requested_locale.toString()); if(log.isDebugEnabled()) log.debug("store locale="+locale); if(locale!=null)invocation.getInvocationContext().getSession().put(attributeName,locale); } //set locale for action Object locale = invocation.getInvocationContext().getSession().get(attributeName); if (locale!=null && locale instanceof Locale) { if(log.isDebugEnabled()) log.debug("apply locale="+locale); invocation.getInvocationContext().setLocale((Locale)locale); } if(log.isDebugEnabled()) log.debug("before Locale="+((ActionSupport)invocation.getAction()).getLocale()); final String result = invocation.invoke(); if(log.isDebugEnabled()) log.debug("after Locale="+((ActionSupport)invocation.getAction()).getLocale()); if(log.isDebugEnabled()) log.debug("intercept } "); return result; } Locale localeFromString(String localeStr) { if ((localeStr == null) || (localeStr.trim().length() == 0) || (localeStr.equals("_"))) { return Locale.getDefault(); } int index = localeStr.indexOf('_'); if (index < 0) { return new Locale(localeStr); } String language = localeStr.substring(0,index); if (index == localeStr.length()) { return new Locale(language); } localeStr = localeStr.substring(index +1); index = localeStr.indexOf('_'); if (index < 0) { return new Locale(language,localeStr); } String country = localeStr.substring(0,index); if (index == localeStr.length()) { return new Locale(language,country); } localeStr = localeStr.substring(index +1); return new Locale(language,country,localeStr); } } Can be enabled for whole package via something like: <interceptor name="i18n" class="neuro.util.xwork.I18nInterceptor"> <!-- on which request parameter we should react, optional, defaults to "request_locale" -> <param name="parameterName">set_locale</param> <!- under which session attribute locale should be stored, optional, defaults to "WW_TRANS_I18N_LOCALE" -> <param name="attributeName">ww_locale</param> </interceptor> <interceptor-stack name="i18nStack"> <interceptor-ref name="i18n"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> <default-interceptor-ref name="i18nStack"/> ...and invoked in web-app just by adding few links to menu: <a href="?set_locale=en">EN</a> <a href="?set_locale=ru">RU</a> <!- etc --> Of course you still need to move all explisitly defined messages or labels to appropriate ResourceBundles and make translations. Be sure to check out your
If this Interceptor is generally useful, may be it should go into codebase? |